package com.wg.db.repository.entity;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;

import java.io.Serializable;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import com.wg.db.repository.code.IRepository;
import com.wg.db.repository.code.MySqlAsyncMapRepository;
import com.wg.db.repository.code.MySqlRepository;

/**
 * 基础实体仓库实现类，封装通用CRUD逻辑
 *
 * @param <K> 主键类型
 * @param <B> Bean类型
 * @param <E> 实体类型
 * @author 少爷123
 */
public abstract class BaseEntityRepository<K extends Serializable, B, E extends IEntity<B>>
        implements IEntityRepository<K, B, E> {
    private static final Log log = LogFactory.get();

    /**
     * 核心仓库实现（通过依赖注入，支持同步/异步）
     */
    protected final IRepository<K, B> repository;

    /**
     * 构造函数（默认使用异步仓库）
     *
     * @param entityClass 实体Bean的Class对象（用于初始化仓库）
     */
    public BaseEntityRepository(Class<B> entityClass) {
        this(entityClass, true);
    }

    /**
     * 构造函数（指定是否使用异步仓库）
     *
     * @param entityClass 实体Bean的Class对象
     * @param async       是否启用异步模式（异步仓库会缓冲操作批量提交）
     */
    public BaseEntityRepository(Class<B> entityClass, boolean async) {
        this.repository = async ? new MySqlAsyncMapRepository<>(entityClass)
                : new MySqlRepository<>(entityClass);
    }

    /**
     * 构造函数（依赖注入，用于测试或灵活替换仓库实现）
     *
     * @param repository 具体的仓库实现（如同步/异步MySQL仓库、Redis仓库等）
     */
    protected BaseEntityRepository(IRepository<K, B> repository) {
        this.repository = Objects.requireNonNull(repository, "repository must not be null");
    }

    @Override
    public B getById(K entityId) {
        return repository.findById(entityId).orElse(null);
    }

    @Override
    public List<B> getByGroupId(Serializable groupId) {
        return repository.findByGroupId(groupId);
    }

    @Override
    public List<B> getAll() {
        return repository.findAll();
    }

    @Override
    public List<B> getBySql(String sql) {
        return repository.findBySql(sql);
    }

    @Override
    public void saveOrUpdate(E entity) {
        Objects.requireNonNull(entity, "entity must not be null");
        B bean = entity.toBean(); // 转换为持久化Bean
        repository.update(bean); // 执行更新（仓库内部处理存在则更新，不存在则插入）
    }

    @Override
    public void batchSaveOrUpdate(List<E> entities) {
        if (CollUtil.isEmpty(entities)) {
            log.warn("批量保存/更新失败：实体列表为空");
            return;
        }

        // 过滤null实体并转换为Bean列表
        List<B> beans = entities.stream()
                .filter(Objects::nonNull)
                .map(E::toBean)
                .collect(Collectors.toList());

        repository.batchUpdate(beans); // 批量更新
    }

    @Override
    public void delete(E entity) {
        Objects.requireNonNull(entity, "entity must not be null");
        B bean = entity.toBean(); // 转换为持久化Bean
        repository.delete(bean); // 执行删除
    }

    @Override
    public void batchDelete(List<E> entities) {
        if (CollUtil.isEmpty(entities)) {
            log.warn("批量删除失败：实体列表为空");
            return;
        }

        // 过滤null实体并转换为Bean列表
        List<B> beans = entities.stream()
                .filter(Objects::nonNull)
                .map(E::toBean)
                .collect(Collectors.toList());

        repository.batchDelete(beans); // 批量删除
    }

    @Override
    public void shutdown() {
        repository.close(); // 关闭仓库资源（如异步线程、数据库连接）
    }

    @Override
    public int pendingSize() {
        // 仅异步仓库（如AbstractMySqlAsyncMapRepository）需要实现size方法
        if (repository instanceof MySqlAsyncMapRepository) {
            return ((MySqlAsyncMapRepository<?, ?>) repository).pendingSize();
        }
        return 0; // 同步仓库无缓冲区，返回0
    }
}